import { screen, Image, ColorMode, Region } from '@nut-tree/nut-js';
import Jimp from 'jimp';
import '@nut-tree/template-matcher';
import cv from 'opencv4nodejs-prebuilt';

/** 根据图标截图、在屏幕中确定位置 */
export async function find(imageBase64Value, confidence = 0.9) {
    const needle = await loadBase64ToImage(imageBase64Value);
    // 1. 初步定位：在整个屏幕中，初步确定截图UI元素位置（TM_SQDIFF_NORMED）
    const locationRegion = await screen.find(needle, {
        confidence,
        providerData: {
            matchMethod: cv.TM_SQDIFF_NORMED,
            scaleSteps: [0.9, 0.8, 0.7, 0.6, 0.5],
        }
    });
    const { left, top, width, height } = locationRegion;

    // 2. 进行判定：在目标区域中，进一步进行UI元素准确度判定（TM_CCOEFF_NORMED）
    const searchRegion = await searchRegionFrom(locationRegion);
    screen.highlight(locationRegion);
    const currentScale = parseFloat((needle.width / locationRegion.width).toFixed(1));
    await screen.find(needle, {
        searchRegion,
        confidence,
        providerData: {
            matchMethod: cv.TM_SQDIFF_NORMED,
            scaleSteps: [0.5, 0.4, 0.3, 0.2, 0.1, -0.1, -0.2, -0.3, -0.4, -0.5]
                .map((scale) => currentScale + scale * 0.1),
        }
    });
    return { x: left, y: top, width, height };
}

async function loadBase64ToImage(imageData) {
    const base64Data = imageData.replace(/^data:image\/\w+;base64/, '');
    const imageBuffer = Buffer.from(base64Data, 'base64');
    return Jimp.read(imageBuffer).then((image) => {
        // stay consistent with images retrieved from libnut which uses BGR format
        image.scan(
            0,
            0,
            image.bitmap.width,
            image.bitmap.height,
            function(_, __, idx) {
                const red = this.bitmap.data[idx];
                this.bitmap.data[idx] = this.bitmap.data[idx + 2];
                this.bitmap.data[idx + 2] = red;
            }
        );
        return new Image(
            image.bitmap.width,
            image.bitmap.height,
            image.bitmap.data,
            4,
            'base64 image',
            image.bitmap.data.length / (image.bitmap.width * image.bitmap.height),
            image.bitmap.data.length / image.bitmap.height,
            ColorMode.BGR
        );
    })
    .catch((err) => {
      throw new Error(`Failed to parse image data. Reason: ${err}`);
    });
}

async function searchRegionFrom(locationRegion) {
    const { left, top, width, height } = locationRegion;
    const searchRegionX = left - width * 0.125 < 0 ? 0 : left - width * 0.125;
    const searchRegionY = top - height * 0.125 < 0 ? 0 : top - height * 0.125;
    const searchRegionWidth = Math.min(width * 1.25, await screen.width() - searchRegionX);
    const searchRegionHeight = Math.min(height * 1.25, await screen.height() - searchRegionY);
    return new Region(
        searchRegionX,
        searchRegionY,
        searchRegionWidth,
        searchRegionHeight
    );
}

export default {
    find,
}